package com.wonders.hisdoctor.station.project.record.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wonders.his.common.bean.BaseResult;
import com.wonders.his.common.exception.CustomException;
import com.wonders.his.common.service.project.base.domain.AppBaseParam;
import com.wonders.his.common.utils.DateUtils;
import com.wonders.his.common.utils.StringUtils;
import com.wonders.his.framework.dto.LoginUserDTO;
import com.wonders.his.framework.service.TokenService;
import com.wonders.his.framework.vo.UserDetailVo;
import com.wonders.hisdoctor.station.constant.ServiceConstant;
import com.wonders.hisdoctor.station.project.base.domain.*;
import com.wonders.hisdoctor.station.project.base.mapper.*;
import com.wonders.hisdoctor.station.project.hisqueue.vo.ClinicMasterQueryVo;
import com.wonders.hisdoctor.station.project.medicine.vo.QryClinicVO;
import com.wonders.hisdoctor.station.project.record.mapper.RecordUseMapper;
import com.wonders.hisdoctor.station.project.record.service.IRecordService;
import com.wonders.hisdoctor.station.project.record.vo.OutpMrPrintVo;
import com.wonders.hisdoctor.station.project.record.vo.OutpMrVo;
import com.wonders.hisdoctor.station.project.record.vo.OutpRequestVo;
import com.wonders.hisdoctor.station.util.CommonUtil;
import com.wonders.hisdoctor.station.util.ConvertUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * Description:
 *
 * @author tong-aj
 * <p>
 * Create: 2021-01-25 09:48
 */

@Service
public class RecordServiceImpl implements IRecordService {

    private OutpMrMapper outpMrMapper;
    private TokenService tokenService;
    private RecordUseMapper recordUseMapper;
    private ClinicMasterMapper clinicMasterMapper;
    private DeptDictMapper deptDictMapper;
    private HospitalDictMapper hospitalDictMapper;
    private PatMasterIndexMapper patMasterIndexMapper;
    private InsuranceAccountsMapper insuranceAccountsMapper;
    private StaffDictMapper staffDictMapper;


    @Override
    public BaseResult<OutpMrVo> queryRecord(OutpRequestVo requestVo) {
        // 查询病历
        OutpMr outpMr = getOutpMr(requestVo);
        // 存在则返回病历信息
        if (outpMr != null) {
            // 将实体类转换成Vo类
            OutpMrVo outpMrVo = ConvertUtils.convertToOutpMrVo(outpMr);
            return BaseResult.success(outpMrVo);
        }
        // 如果为空，则赋值标志位
        OutpMrVo outpMrVo = new OutpMrVo();
        outpMrVo.setPatientId(requestVo.getPatientId());
        outpMrVo.setVisitDate(DateUtils.dateFormatDate(DateUtils.YYYY_MM_DD, requestVo.getVisitDate()));
        outpMrVo.setVisitNo(requestVo.getVisitNo());
        return BaseResult.success(outpMrVo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult<String> saveRecord(OutpMrVo outpMrVo, HttpServletRequest request) {
        // 将Vo类转换成实体类
        OutpMr outpMr = ConvertUtils.convertToOutpMr(outpMrVo);
        // 疾病下拉框
        outpMr.setDiagDesc(getDiagValueOfCodes(outpMrVo.getDiagnosisCode()));
        // 中医诊断
        outpMr.setTmDiagDesc(getTmDiagValueOfCodes(outpMrVo.getTmDiagCode()));
        // 中医诊断证型
        outpMr.setTmTypeDesc(getTmTypeValueOfCodes(outpMrVo.getTmTypeCode()));
        validate(outpMr);
        OutpRequestVo requestVo = new OutpRequestVo();
        BeanUtils.copyProperties(outpMrVo, requestVo);
        requestVo.setEmpNo(outpMrVo.getDoctor());

        // 防止前端漏传empNo
        String hospitalCode;
        UserDetailVo sysSysuserVo = null;
        if (StringUtils.isEmpty(requestVo.getEmpNo())) {
            sysSysuserVo = tokenService.getLoginUserDTO(tokenService.getToken(request)).getSysSysuserVo();
            String empNo = sysSysuserVo.getEmpNo();
            requestVo.setEmpNo(empNo);
            outpMr.setDoctor(empNo);
        }

        OutpMr outpMrFromDb = getOutpMr(requestVo);
        if (outpMrFromDb == null) {
            // 新增时，判断是否有其他医生已经有该病人的病历
            requestVo.setEmpNo("");
            OutpMr outpMrNoEmp = getOutpMr(requestVo);
            if (outpMrNoEmp != null) {
                // 如果有，则新增的病历ordinal+1
                outpMr.setOrdinal(outpMrNoEmp.getOrdinal() + 1);
            } else {
                outpMr.setOrdinal(1);
            }
            // 1: 表示是从候诊队列获取的病人，新增病历
            outpMr.setMrCreator(outpMr.getDoctor());
            outpMrMapper.insert(outpMr);
        } else {
            // 其他情况则是更新病历
            outpMr.setOrdinal(outpMrFromDb.getOrdinal());
            outpMrMapper.updateOutpMr(outpMr);
        }
        if(sysSysuserVo != null){
            hospitalCode = sysSysuserVo.getHospitalCode();
            saveEditorSupport(outpMrVo,hospitalCode);
        }
        return BaseResult.success("保存成功");
    }


    @Autowired
    private WdeditorDssetMapper dssetMapper;

    /**
    * Description: 病历模板辅助表保存
    * Param: [outpMrVo, hospitalCode]
    * return: void
    * Author: tong-aj
    * Date: 2021/7/22
    */
    private void saveEditorSupport(OutpMrVo outpMrVo, String hospitalCode) {
        WdeditorSupport wdeditorSupport = new WdeditorSupport();
        wdeditorSupport.setDoctor(outpMrVo.getDoctor());
        wdeditorSupport.setHospitalCode(hospitalCode);
        List<WdeditorDsset> wdeditorDssets = dssetMapper.selectList(new QueryWrapper<WdeditorDsset>().eq("ORG_ID", hospitalCode).eq("DEFAULT_FLAG", ServiceConstant.ONE_STRING));
        if(CollUtil.isNotEmpty(wdeditorDssets)){
            wdeditorSupport.setModelId(wdeditorDssets.get(0).getModelId());
        }
        wdeditorSupport.setPatientId(outpMrVo.getPatientId());
        wdeditorSupport.setTitle(commonUtil.setPrintTitle(hospitalCode));
        wdeditorSupport.setVisitDate(outpMrVo.getVisitDate());
        wdeditorSupport.setVisitNo(outpMrVo.getVisitNo());
    }

    private void validate(OutpMr outpMr) {
        if (StringUtils.isNotEmpty(outpMr.getDiagnosisCode()) && StringUtils.isNotEmpty(outpMr.getDiagDesc())) {
            if (outpMr.getDiagnosisCode().length() > 100 || outpMr.getDiagDesc().length() > 200) {
                throw new CustomException("西医诊断字段超长，无法保存");
            }
        }
        if (StringUtils.isNotEmpty(outpMr.getTmDiagCode()) && StringUtils.isNotEmpty(outpMr.getTmDiagDesc())) {
            if (outpMr.getTmDiagCode().length() > 100 || outpMr.getTmDiagDesc().length() > 400) {
                throw new CustomException("中医诊断字段超长，无法保存");
            }
        }
        if (StringUtils.isNotEmpty(outpMr.getTmTypeCode()) && StringUtils.isNotEmpty(outpMr.getTmTypeDesc())) {
            if (outpMr.getTmTypeCode().length() > 100 || outpMr.getTmTypeDesc().length() > 400) {
                throw new CustomException("证型字段超长，无法保存");
            }
        }
    }

    /**
     * Description: 根据中医诊断证型code查询诊断name
     * Param: [tmTypeCode]
     * return: java.lang.String
     * Author: tong-aj
     * Date: 2021/3/9
     */
    private String getTmTypeValueOfCodes(String tmTypeCode) {
        if (StringUtils.isNotEmpty(tmTypeCode)) {
            List<String> strings = Arrays.asList(tmTypeCode.split(","));
            List<Map<String, String>> tmTypeValueOfCodesMap = recordUseMapper.getTmTypeValueOfCodes(strings);
            StringBuilder tmTypeValueOfCodes = new StringBuilder();
            strings.forEach(e -> {
                Optional<Map<String, String>> any = tmTypeValueOfCodesMap.stream().filter(map -> map.containsValue(e)).findAny();
                any.ifPresent(map -> tmTypeValueOfCodes.append(map.get(ServiceConstant.TM_TYPE_NAME)).append(","));

            });
            return tmTypeValueOfCodes.substring(0, tmTypeValueOfCodes.length() - 1);
        } else {
            return "";
        }
    }

    /**
     * Description: 根据中医诊断code查询诊断name
     * Param: [tmDiagCode]
     * return: java.lang.String
     * Author: tong-aj
     * Date: 2021/3/8
     */
    private String getTmDiagValueOfCodes(String tmDiagCode) {
        if (StringUtils.isNotEmpty(tmDiagCode)) {
            List<String> strings = Arrays.asList(tmDiagCode.split(","));
            List<Map<String, String>> tmDiagValueOfCodesMap = recordUseMapper.getTmDiagValueOfCodes(strings);
            StringBuilder tmDiagValueOfCodes = new StringBuilder();
            strings.forEach(e -> {
                Optional<Map<String, String>> any = tmDiagValueOfCodesMap.stream().filter(map -> map.containsValue(e)).findAny();
                any.ifPresent(map -> tmDiagValueOfCodes.append(map.get(ServiceConstant.TM_DIAG_NAME)).append(","));
            });
            return tmDiagValueOfCodes.substring(0, tmDiagValueOfCodes.length() - 1);
        } else {
            return "";
        }
    }

    /**
     * Description: 根据诊断code查询诊断name
     * Param: [diagnosisCode]
     * return: java.lang.String
     * Author: tong-aj
     * Date: 2021/3/8
     */
    private String getDiagValueOfCodes(String diagnosisCode) {
        if (StringUtils.isNotEmpty(diagnosisCode)) {
            List<String> strings = Arrays.asList(diagnosisCode.split(","));
            List<Map<String, String>> diagValueOfCodesMap = recordUseMapper.getDiagValueOfCodes(strings);
            StringBuilder diagValueOfCodes = new StringBuilder();
            strings.forEach(e -> {
                Optional<Map<String, String>> any = diagValueOfCodesMap.stream().filter(map -> map.containsValue(e)).findAny();
                any.ifPresent(map -> diagValueOfCodes.append(map.get(ServiceConstant.DIAGNOSIS_NAME)).append(","));
            });
            return diagValueOfCodes.substring(0, diagValueOfCodes.length() - 1);
        } else {
            return "";
        }
    }

    @Autowired
    private CommonUtil commonUtil;

    @Override
    public BaseResult<String> checkDiagnose(OutpRequestVo requestVo) {
        // 查询病历
        OutpMr outpMr = getOutpMr(requestVo);
        // 验证
        // 查询全局配置，是否存在DIAG_NULL_ALLOW，并且为0，即诊断为空，不允许进行后续页面
        AppBaseParam appBaseParam = commonUtil.getAppBaseParam(requestVo.getHospitalCode(), ServiceConstant.DIAG_NULL_ALLOW, ServiceConstant.HOSPITAL_LONG);
        if (appBaseParam != null && appBaseParam.getValueName().equals(ServiceConstant.ZERO_STRING)) {
            if (outpMr == null) {
                return BaseResult.fail("当前患者不存在病历");
            } else {
                if (StringUtils.isEmpty(outpMr.getDiagnosisCode())
                        || StringUtils.isEmpty(outpMr.getDiagDesc())) {
                    return BaseResult.fail("当前患者病历的诊断为空");
                }
            }
        }
        return BaseResult.success();
    }

    /**
     * Description: 打印
     * Param: [patientId, visitDate, visitNo]
     * return: com.wonders.hisdoctor.station.project.record.vo.OutpMrPrintVo
     * Author: tong-aj
     * Date: 2021/3/12
     */
    @Override
    public OutpMrPrintVo print(String patientId, Date visitDate, String visitNo, HttpServletRequest request) {
        // 组装病人信息
        QueryWrapper<ClinicMaster> clinicMasterQueryWrapper = new QueryWrapper<>();
        clinicMasterQueryWrapper.eq(ServiceConstant.VISIT_DATE, visitDate).eq(ServiceConstant.VISIT_NO, visitNo).eq(ServiceConstant.PATIENT_ID, patientId);
        ClinicMaster clinicMaster = clinicMasterMapper.selectOne(clinicMasterQueryWrapper);
        OutpMrPrintVo printVo = new OutpMrPrintVo();
        if (clinicMaster != null) {
            ConvertUtils.convertClinicMasterToOutpMrPrintVo(printVo, clinicMaster);
            if (StringUtils.isNotEmpty(clinicMaster.getVisitDept())) {
                DeptDict deptDict = deptDictMapper.selectOne(new QueryWrapper<DeptDict>().eq(ServiceConstant.DEPT_CODE, clinicMaster.getVisitDept()));
                printVo.setDepName(deptDict.getDeptName());
            }
            String empNo = "";
            // 机构名称
            LoginUserDTO loginUserDTO = tokenService.getLoginUserDTO(tokenService.getToken(request));
            if (loginUserDTO != null) {
                empNo = loginUserDTO.getSysSysuserVo().getEmpNo();
                HospitalDict hospitalDict = hospitalDictMapper.selectOne(new QueryWrapper<HospitalDict>().eq(ServiceConstant.HOSPITAL_CODE, loginUserDTO.getSysSysuserVo().getHospitalCode()));
                if (hospitalDict != null) {
                    printVo.setHospitalName(hospitalDict.getHospitalName());
                }
            }
            // 组装病历信息
            QueryWrapper<OutpMr> outpMrQueryWrapper = new QueryWrapper<>();
            outpMrQueryWrapper
                    .eq(ServiceConstant.VISIT_DATE, visitDate)
                    .eq(ServiceConstant.VISIT_NO, visitNo)
                    .eq(ServiceConstant.PATIENT_ID, patientId)
                    .eq(ServiceConstant.DOCTOR, empNo);
            OutpMr outpMr = outpMrMapper.selectOne(outpMrQueryWrapper);
            if (outpMr != null) {
                ConvertUtils.convertOutpMrToOutpMrPrintVo(printVo, outpMr);
            }

            PatMasterIndex patMasterIndex = patMasterIndexMapper.selectOne(new QueryWrapper<PatMasterIndex>().eq(ServiceConstant.PATIENT_ID, patientId).eq(ServiceConstant.CHARGE_TYPE, clinicMaster.getChargeType()).eq(ServiceConstant.IDENTITY, clinicMaster.getIdentity()));
            if (patMasterIndex != null) {
                printVo.setDateBirth(DateUtils.dateFormatTime(patMasterIndex.getDateOfBirth(), "yyyy/MM/dd"));
            }
            // 封装dateBirth和婚姻状况
            InsuranceAccounts insuranceAccounts = insuranceAccountsMapper.selectOne(new QueryWrapper<InsuranceAccounts>().eq(ServiceConstant.PATIENT_ID, patientId));
            if (insuranceAccounts != null) {
                printVo.setMaritalStatus(insuranceAccounts.getMaritalStatus());
            }
        }
        return printVo;
    }

    @Override
    public BaseResult<OutpMrVo> queryRecordHistory(OutpRequestVo requestVo) {
        BaseResult<OutpMrVo> outpMrVoBaseResult = queryRecord(requestVo);
        OutpMrVo data = outpMrVoBaseResult.getData();
        String doctor = data.getDoctor();
        if (StringUtils.isNotEmpty(doctor)) {
            StaffDict emp = staffDictMapper.selectOne(new QueryWrapper<StaffDict>().eq(ServiceConstant.EMP_NO, doctor));
            data.setDoctor(emp.getName());
        }
        return BaseResult.success(data);
    }

    @Override
    public List<ClinicMasterQueryVo> selectMrList(QryClinicVO clinicVO) {
        return recordUseMapper.selectMrList(clinicVO);
    }

    private OutpMr getOutpMr(OutpRequestVo requestVo) {
        QueryWrapper<OutpMr> queryWrapper = new QueryWrapper<>();
        // 根据就诊信息的：visit_no、visit_date、patient_id 来查看病历信息

        queryWrapper
                .eq(ServiceConstant.VISIT_NO, requestVo.getVisitNo())
                .eq(ServiceConstant.VISIT_DATE, requestVo.getVisitDate())
                .eq(ServiceConstant.PATIENT_ID, requestVo.getPatientId());
        if (StringUtils.isNotEmpty(requestVo.getEmpNo())) {
            queryWrapper.eq(ServiceConstant.DOCTOR, requestVo.getEmpNo());
            return outpMrMapper.selectOne(queryWrapper);
        } else {
            queryWrapper.orderByDesc(ServiceConstant.ORDINAL);
            List<OutpMr> outpMrs = outpMrMapper.selectList(queryWrapper);
            return CollectionUtils.isEmpty(outpMrs) ? null : outpMrs.get(0);

        }
    }

    @Autowired
    public void setOutpMrMapper(OutpMrMapper outpMrMapper) {
        this.outpMrMapper = outpMrMapper;
    }

    @Autowired
    public void setTokenService(TokenService tokenService) {
        this.tokenService = tokenService;
    }

    @Autowired
    public void setRecordUseMapper(RecordUseMapper recordUseMapper) {
        this.recordUseMapper = recordUseMapper;
    }

    @Autowired
    public void setClinicMasterMapper(ClinicMasterMapper clinicMasterMapper) {
        this.clinicMasterMapper = clinicMasterMapper;
    }

    @Autowired
    public void setDeptDictMapper(DeptDictMapper deptDictMapper) {
        this.deptDictMapper = deptDictMapper;
    }

    @Autowired
    public void setHospitalDictMapper(HospitalDictMapper hospitalDictMapper) {
        this.hospitalDictMapper = hospitalDictMapper;
    }

    @Autowired
    public void setPatMasterIndexMapper(PatMasterIndexMapper patMasterIndexMapper) {
        this.patMasterIndexMapper = patMasterIndexMapper;
    }

    @Autowired
    public void setInsuranceAccountsMapper(InsuranceAccountsMapper insuranceAccountsMapper) {
        this.insuranceAccountsMapper = insuranceAccountsMapper;
    }

    @Autowired
    public void setStaffDictMapper(StaffDictMapper staffDictMapper) {
        this.staffDictMapper = staffDictMapper;
    }
}
